package com.fsnbigdata.web;
import com.fsnbigdata.domain.Ecosystem;
import com.fsnbigdata.domain.EndangeredSpecies;
import com.fsnbigdata.domain.dto.NamingPair2;
import com.fsnbigdata.domain.query.EcosystemQueryDslBinder;
import com.fsnbigdata.domain.query.EndangeredSpeciesQueryDslBinder;
import com.fsnbigdata.enums.ResultEnum;
import com.fsnbigdata.exception.ParamException;
import com.fsnbigdata.util.ReflectUtil;
import com.querydsl.core.types.Predicate;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.querydsl.binding.QuerydslPredicate;
import org.springframework.roo.addon.web.mvc.controller.annotations.ControllerType;
import org.springframework.roo.addon.web.mvc.controller.annotations.RooController;
import org.springframework.roo.addon.web.mvc.controller.annotations.responses.json.RooJSON;
import com.fsnbigdata.service.api.EndangeredSpeciesService;
import io.springlets.data.domain.GlobalSearch;

import java.lang.reflect.Method;
import java.security.Principal;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
import org.springframework.web.util.UriComponents;
import springfox.documentation.annotations.ApiIgnore;

/**
 * = EndangeredSpeciesesCollectionJsonController
 *
 * TODO Auto-generated class documentation
 *
 */
@RooController(entity = EndangeredSpecies.class, pathPrefix = "/api", type = ControllerType.COLLECTION)
@RooJSON
@RestController
@RequestMapping(value = "/api/endangeredspecies", name = "EndangeredSpeciesesCollectionJsonController", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(tags = "EndangeredSpecieses", description = "濒危生物" )
public class EndangeredSpeciesesCollectionJsonController {

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private EndangeredSpeciesService endangeredSpeciesService;

    /**
     * TODO Auto-generated constructor documentation
     *
     * @param endangeredSpeciesService
     */
    @Autowired
    public EndangeredSpeciesesCollectionJsonController(EndangeredSpeciesService endangeredSpeciesService) {
        this.endangeredSpeciesService = endangeredSpeciesService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return EndangeredSpeciesService
     */
    public EndangeredSpeciesService getEndangeredSpeciesService() {
        return endangeredSpeciesService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param endangeredSpeciesService
     */
    public void setEndangeredSpeciesService(EndangeredSpeciesService endangeredSpeciesService) {
        this.endangeredSpeciesService = endangeredSpeciesService;
    }

    @GetMapping(name = "index", value = "index")
    public ResponseEntity<List<NamingPair2>> category(
        @ApiParam @RequestParam(required = false) String initial) {
        List<NamingPair2> namingPairs = getEndangeredSpeciesService().findAllByInitial(initial);
        return ResponseEntity.ok(namingPairs);
    }

    /**
     * @param query
     * @param pageable
     * @return
     */
    @GetMapping(name = "search", value = "search")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "size", defaultValue = "20", dataType = "int", paramType = "query")
    })
    public ResponseEntity<Page<EndangeredSpecies>> search(
            @ApiParam @RequestParam(required = false) String query,
            Pageable pageable) {
        GlobalSearch globalSearch = StringUtils.isNotBlank(query) ? new GlobalSearch(query, false) : null;
        Page<EndangeredSpecies> endangeredSpecieses = getEndangeredSpeciesService().findAll(globalSearch, pageable);
        return ResponseEntity.ok(endangeredSpecieses);
    }
    /**
     * 前台列表
     * @param request
     * @param pageable
     * @return
     */
    @GetMapping("getList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "size", defaultValue = "20", dataType = "int", paramType = "query")
    })
    public List getList(HttpServletRequest request,Pageable pageable){
        String name = request.getParameter( "name" );
        String latin = request.getParameter( "latin" );
        String sort = request.getParameter( "content" );
        Pageable pageable1 = new PageRequest( pageable.getPageNumber(),pageable.getPageSize(),new Sort( "asc".equals( sort )? Sort.Direction.ASC: Sort.Direction.DESC,"id" ) );
        return endangeredSpeciesService.getPageList(name,latin,pageable1);
    }
    /**
     *
     * @param predicate
     * @param pageable
     * @return
     */
    @GetMapping(name = "search", value = "advanceSearch")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "size", defaultValue = "20", dataType = "int", paramType = "query")
    })
    public ResponseEntity<Page<EndangeredSpecies>> advanceSearch(
            @ApiParam @QuerydslPredicate(root = EndangeredSpecies.class, bindings = EndangeredSpeciesQueryDslBinder.class) Predicate predicate,
            Pageable pageable) {
        Page<EndangeredSpecies> endangeredSpecies = getEndangeredSpeciesService().search(predicate, pageable);
        return ResponseEntity.ok(endangeredSpecies);
    }

    /**
     * @param authentication
     * @param query
     * @param pageable
     * @return
     */
    @GetMapping(name = "list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", defaultValue = "0", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "size", defaultValue = "20", dataType = "int", paramType = "query")
    })
    @PreAuthorize("hasRole('DB_ES_CS')")
    public ResponseEntity<Page<EndangeredSpecies>> list(
            Authentication authentication,
            @ApiParam @RequestParam(required = false) String query,
            Pageable pageable) {
        GlobalSearch globalSearch = StringUtils.isNotBlank(query) ? new GlobalSearch(query, false) : null;
        Page<EndangeredSpecies> endangeredSpecieses = null;
        List<String> authorities = authentication.getAuthorities().stream().map(it -> it.getAuthority()).collect(Collectors.toList());
        if(!authorities.contains("ROLE_USER_ADMIN")){
            endangeredSpecieses = getEndangeredSpeciesService().findAll(globalSearch, pageable, authentication.getName());
        }else{
            endangeredSpecieses = getEndangeredSpeciesService().findAll(globalSearch, pageable);
        }
        return ResponseEntity.ok(endangeredSpecieses);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return UriComponents
     */
    public static UriComponents listURI() {
        return MvcUriComponentsBuilder.fromMethodCall(MvcUriComponentsBuilder.on(EndangeredSpeciesesCollectionJsonController.class).list(null,null, null)).build().encode();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param endangeredSpecies
     * @param result
     * @return ResponseEntity
     */
    @PostMapping(name = "create")
    @PreAuthorize("hasRole('DB_ES_CS')")
    @ApiOperation(value = "",notes = "save")
    public ResponseEntity<?> create(
            @Valid @RequestBody EndangeredSpecies endangeredSpecies,
            BindingResult result,
            Principal principal) throws Exception {
        if (endangeredSpecies.getId() != null || endangeredSpecies.getVersion() != null) {
            return ResponseEntity.status(HttpStatus.CONFLICT).build();
        }
        if (result.hasErrors()) {
            throw new ParamException(ResultEnum.PARAM_ERROR.getCode(),
                    result.getFieldError().getDefaultMessage());
        }

        endangeredSpecies.setCreator(principal.getName());

        endangeredSpecies.getImages().forEach(it -> it.setEndangeredSpecies(endangeredSpecies));

        EndangeredSpecies newEndangeredSpecies = getEndangeredSpeciesService().save(endangeredSpecies);
        UriComponents showURI = EndangeredSpeciesesItemJsonController.showURI(newEndangeredSpecies);

        Class<?> clazz = EndangeredSpeciesesCollectionJsonController.class;
        Method method = clazz.getMethod("create", ReflectUtil.getPeremeterClass(clazz, "create"));
        ReflectUtil.setAnnotationOn(method,"新增濒危生物，中文名："+newEndangeredSpecies.getName());

        return ResponseEntity.ok(newEndangeredSpecies);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param endangeredSpecieses
     * @param result
     * @return ResponseEntity
     */
    @PostMapping(value = "/batch", name = "createBatch")
    @PreAuthorize("hasRole('DB_ES_CS')")
    @ApiIgnore
    public ResponseEntity<?> createBatch(@Valid @RequestBody Collection<EndangeredSpecies> endangeredSpecieses, BindingResult result) {
        if (result.hasErrors()) {
            return ResponseEntity.status(HttpStatus.CONFLICT).body(result);
        }

        endangeredSpecieses.forEach(endangeredSpecies -> endangeredSpecies.getImages().forEach(it -> it.setEndangeredSpecies(endangeredSpecies)));

        getEndangeredSpeciesService().save(endangeredSpecieses);
        return ResponseEntity.created(listURI().toUri()).build();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param endangeredSpecieses
     * @param result
     * @return ResponseEntity
     */
    @PutMapping(value = "/batch", name = "updateBatch")
    @PreAuthorize("hasRole('DB_ES_CS')")
    @ApiIgnore
    public ResponseEntity<?> updateBatch(@Valid @RequestBody Collection<EndangeredSpecies> endangeredSpecieses, BindingResult result) {
        if (result.hasErrors()) {
            return ResponseEntity.status(HttpStatus.CONFLICT).body(result);
        }

        endangeredSpecieses.forEach(endangeredSpecies -> endangeredSpecies.getImages().forEach(it -> it.setEndangeredSpecies(endangeredSpecies)));

        getEndangeredSpeciesService().save(endangeredSpecieses);
        return ResponseEntity.ok().build();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param ids
     * @return ResponseEntity
     */
    @DeleteMapping(value = "/batch/{ids}", name = "deleteBatch")
    @PreAuthorize("hasRole('DB_ES_CS')")
    @ApiIgnore
    public ResponseEntity<?> deleteBatch(@PathVariable("ids") Collection<Long> ids) {
        getEndangeredSpeciesService().delete(ids);
        return ResponseEntity.ok().build();
    }

    @GetMapping(name = "find" , value="find")
    public EndangeredSpecies findById(String id){
        return endangeredSpeciesService.findOne( Long.parseLong( id ) );
    }
}
